const config = require("@/common/config")

let tool = {
	/**
	 * 显示模态弹窗
	 * @param content 提示的标题
	 */
	showConfirm(content) {
		return new Promise((resolve, reject) => {
			uni.showModal({
				title: '提示',
				content: content,
				cancelText: '取消',
				confirmText: '确定',
				confirmColor: '#EBB747',
				cancelColor: '#999999',
				success: function(res) {
					resolve(res)
				}
			})
		})
	},

	// 断网
	isHaveNetwork() {
		uni.getNetworkType({
			success: (res) => {
				if (res.networkType === 'none') {
					uni.showModal({
						title: '当前无网络连接!',
						content: '请您检查网络是否链接正常!请打开WIFI或者移动数据。',
						success: (res) => {
							if (res.confirm) {
								uni.navigateTo({
									url: '/pages/404/404.vue'
								})
							} else {
								uni.navigateTo({
									url: '/pages/404/404.vue'
								})
							}
						}
					});
				} else {
					console.log('网络已连接,可以正常访问!') //有网
				}
				setTimeout(function() {
					return res.networkType
				}, 500);
			}
		});
	},

	/**
	 * 计算两个经纬度之间的直线距离（Haversine公式）
	 * @param {Object} pointA - 第一个点 { lat: 纬度, lng: 经度 }
	 * @param {Object} pointB - 第二个点 { lat: 纬度, lng: 经度 }
	 * @param {string} [unit='km'] - 返回单位: 'km' 公里 | 'mi' 英里
	 * @returns {number} 两点间的直线距离（保留两位小数）
	 */
	getDistanceBetweenCoordinates(pointA, pointB, unit = 'km') {
        // 将经纬度转换为弧度
        const toRadians = (degree) => degree * (Math.PI / 180);

        const lat1 = toRadians(pointA.lat);
        const lng1 = toRadians(pointA.lng);
        const lat2 = toRadians(pointB.lat);
        const lng2 = toRadians(pointB.lng);

        // 经纬度差值
        const dLat = lat2 - lat1;
        const dLng = lng2 - lng1;

        // Haversine公式计算
        const a =
            Math.sin(dLat / 2) ** 2 +
            Math.cos(lat1) * Math.cos(lat2) *
            Math.sin(dLng / 2) ** 2;

        const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 地球半径（单位：公里）
        const EARTH_RADIUS = unit === 'mi' ? 3956 : 6371; // 英里:3956 公里:6371

        // 计算距离并保留两位小数
        const distance = EARTH_RADIUS * c;
        return Math.round(distance * 100) / 100;
    },

	/**
	 * 参数处理
	 * @param params 参数
	 */
	tansParams(params) {
		let result = ''
		for (const propName of Object.keys(params)) {
			const value = params[propName]
			var part = encodeURIComponent(propName) + "="
			if (value !== null && value !== "" && typeof(value) !== "undefined") {
				if (typeof value === 'object') {
					for (const key of Object.keys(value)) {
						if (value[key] !== null && value[key] !== "" && typeof(value[key]) !== 'undefined') {
							let params = propName + '[' + key + ']'
							var subPart = encodeURIComponent(params) + "="
							result += subPart + encodeURIComponent(value[key]) + "&"
						}
					}
				} else {
					result += part + encodeURIComponent(value) + "&"
				}
			}
		}
		return result
	},

	/**
	 * 获取url中指定参数值，兼容h5路由hash模式
	 * @param {string} url  url地址
	 * @param {string} name  参数名
	 * @returns {string|null} 返回参数值，如果未找到则返回 null
	 */
	getUrlVal(url, name) {
		let reg = "(\\?|&)"+name+"=([^&]\\w+)"
		const value = url.match(new RegExp(reg));

		if (!value || value.length === 0) return null;

		return value[2];
	},

	//对象参数转为以？&拼接的字符
	paramsToStr(params) {
		let p = '';
		if (typeof params == 'object') {
			p = '?'
			for (let props in params) {
				p += `${props}=${params[props]}&`
			}
			p = p.slice(0, -1)
		}
		return p
	},

	/**
	 * toast提示框
	 * @param info 提示信息
	 * @param navigateOpt 跳转页面配置
	 */
	toast(info = {}, navigateOpt) {
		let title,icon,endtime;

		if(typeof info === 'string') {
			title = info || ""
			icon = 'none'
			endtime = 2000
		} else {
			title = info.title || ""
			icon = info.icon || 'none'
			endtime = info.endtime || 2000
		}

		if (title) uni.showToast({
			title: title,
			icon: icon,
			duration: endtime
		})
		if (navigateOpt !== undefined) {
			if (typeof navigateOpt == 'object') {
				let tab = navigateOpt.tab || 1,
					url = navigateOpt.url || '';
				switch (tab) {
					case 1:
						//跳转至 table
						setTimeout(function () {
							uni.switchTab({
								url: url
							})
						}, endtime);
						break;
					case 2:
						//跳转至非table页面
						setTimeout(function () {
							uni.navigateTo({
								url: url,
							})
						}, endtime);
						break;
					case 3:
						//返回上页面
						setTimeout(function () {
							uni.navigateBack({
								delta: parseInt(url),
							})
						}, endtime);
						break;
					case 4:
						//关闭当前所有页面跳转至非table页面
						setTimeout(function () {
							uni.reLaunch({
								url: url,
							})
						}, endtime);
						break;
					case 5:
						//关闭当前页面跳转至非table页面
						setTimeout(function () {
							uni.redirectTo({
								url: url,
							})
						}, endtime);
						break;
				}

			} else if (typeof navigateOpt == 'function') {
				setTimeout(function () {
					navigateOpt && navigateOpt();
				}, endtime);
			}
		}
	},

	/**
	 * Loading加载提示框
	 * @param {string} title 	加载提示文本信息
	 */
	showLoading(title) {
		uni.showLoading({
			title: title
		})
	},

	/**
	 * 时获取字符串的真实长度（字节长度）
	 * @param {string} str 	传入字符串
	 */
	strLeng(str) {
		if (str) {
			let len = str.length,
				truelen = 0;
			for (let x = 0; x < len; x++) {
				if (str.charCodeAt(x) > 128) {
					truelen += 2;
				} else {
					truelen += 1;
				}
			}
			return truelen;
		} else {
			return 0;
		}
	},

	/**
	 * 生成随机颜色功能函数
	 *  @return {string} 返回str
	*/
	getRandomColor() {
		const rgb = [];
		for (let i = 0; i < 3; ++i) {
			let color = Math.floor(Math.random() * 256).toString(16)
			color = color.length == 1 ? '0' + color : color
			rgb.push(color)
		}
		return '#' + rgb.join('');
	},

	/**
	 * 格式化字符串时间
	 * @param {String} dateTime 时间字符串
	 * @return {Date} 返回Date实例对象
	 */
	strToTime(dateTime = null) {
		let date
		// 若传入时间为假值，则取当前时间
		if (!dateTime) {
			date = new Date()
		}
		// 若为unix秒时间戳，则转为毫秒时间戳（逻辑有点奇怪，但不敢改，以保证历史兼容）
		else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
			date = new Date(dateTime * 1000)
		}
		// 若用户传入字符串格式时间戳，new Date无法解析，需做兼容
		else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
			date = new Date(Number(dateTime))
		}
			// 处理平台性差异，在Safari/Webkit中，new Date仅支持/作为分割符的字符串时间
		// 处理 '2022-07-10 01:02:03'，跳过 '2022-07-10T01:02:03'
		else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
			date = new Date(dateTime.replace(/-/g, '/'))
		}
		// 其他都认为符合 RFC 2822 规范
		else {
			date = new Date(dateTime)
		}

		return date
	},

	/**
	 * @description 格式化时间
	 * @param {String|Number} dateTime 需要格式化的时间戳
	 * @param {String} formatStr 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
	 * @returns {string} 返回格式化后的字符串
	 */
	timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
		let date = this.strToTime(dateTime)

		const timeSource = {
			'y': date.getFullYear().toString(), // 年
			'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
			'd': date.getDate().toString().padStart(2, '0'), // 日
			'h': date.getHours().toString().padStart(2, '0'), // 时
			'M': date.getMinutes().toString().padStart(2, '0'), // 分
			's': date.getSeconds().toString().padStart(2, '0') // 秒
			// 有其他格式化字符需求可以继续添加，必须转化成字符串
		}

		for (const key in timeSource) {
			const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
			if (ret) {
				// 年可能只需展示两位
				const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
				formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
			}
		}

		return formatStr
	},

	/**
	 * 计算订单过期时间剩余的毫秒数
	 * @param {*} timeParam 传入的时间参数，将由strToTime转换为Date对象
	 * @returns {number} 剩余毫秒数（可能为负数，表示已过期的时间）
	 */
	getRemainingMs(timeParam) {
		const expireDate = this.strToTime(timeParam);
		const now = new Date(); // 当前时间
		return expireDate.getTime() - now.getTime();
	},

	/**
	 * 判断给定数据是否为空
	 * @param {any} data
	 * @return {Boolean}
	 */
	isDataEmpty(data) {
		if (data === null || data === undefined) {
			return true;
		}

		if (typeof data === 'string' && data.trim() === '') {
			return true;
		}

		if (typeof data === 'number' && isNaN(data)) {
			return true;
		}

		if (Array.isArray(data) && data.length === 0) {
			return true;
		}

		if (typeof data === 'object' && Object.keys(data).length === 0) {
			return true;
		}

		return false;
	},

	// 防抖函数
	debounce(fn, delay) {
		let timer
		return function() {
			const that = this
			const _args = arguments // 存一下传入的参数
			if (timer) {
				clearTimeout(timer)
			}
			timer = setTimeout(function() {
				fn.apply(that, _args)
			}, delay)
		}
	},

	/**
	 * 节流函数
	 * @param fn
	 * @param gapTime
	 * @returns {(function(): void)|*}
	 */
	throttle(fn, gapTime) {
		if (gapTime == null || gapTime == undefined) {
			gapTime = 1500
		}
		let _lastTime = null
		// 返回新的函数
		return function() {
			let _nowTime = +new Date()
			if (_nowTime - _lastTime > gapTime || !_lastTime) {
				fn.apply(this, arguments) //将this和参数传给原函数
				_lastTime = _nowTime
			}
		}
	},

	/**
	 * 获取对象值，仿照lodash的get实现
	 * @param object {Object} 对象
	 * @param path {string} 输入的路径
	 * @param defaultVal 默认值
	 **/
	get(object, path, defaultVal='') {
		// 先将path处理成统一格式
		let newPath = [];
		if (Array.isArray(path)) {
			newPath = path;
		} else {
			// 先将字符串中的'['、']'去除替换为'.'，split分割成数组形式
			newPath = path.replace(/\[/g,'.').replace(/\]/g,'').split('.');
		}

		// 递归处理，返回最后结果
		return newPath.reduce((o, k) => {
			return (o || {})[k]
		}, object) || defaultVal;
	},

	/**
	 * 生成占位测试图
	 * @param {string|number} 	width 		宽度
	 * @param {string|number} 	height 		高度
	 * @param {string} text 占位文字
	 */
	createTestImg(width = 300, height = 150,text = "") {
		return `http://iph.href.lu/${width}x${height}?text=${text}`
	},

	/**
	 * 传入对象结构和生成的长度，批量生成对应数据列表
	 * @param {object} 	obj 		传入的对象
	 * @param {number} 	length 		生成的长度
	 * @returns {array} 返回的数据列表
	 */
	createTestList(obj, length) {
		let list = [];
		for (let i = 0; i < length; i++) {
			let item = {};
			for (let key in obj) {
				if (typeof obj[key] === "function") {
					item[key] = obj[key]();
				} else {
					item[key] = obj[key];
				}
			}
			list.push(item);
		}
		return list;
	},
};

export default tool;
